import json, base64, os, re
import requests, asyncio, fitz
from tools.to_log import log

from tools.prompt_handler import prompt_hanlder


# 获取错误返回
def get_code(code, message="服务器错误，请稍后重试"):
    return {"code": code, "message": base64.b64encode(message.encode('utf-8')).decode('utf-8')}


def return_code(code, contract_id, obj):
    log.info('return_code is start')
    data = {"contract_id": contract_id, "message": obj}
    if code == 200:
        data_dic = {}
        data_dic['J'] = {}
        data_dic['X'] = []
        xdr_dic = {}
        data_dic['J']['合同编号'] = obj['合同编号']
        data_dic['J']['合同名称'] = obj['合同名称']
        data_dic['J']['联系人'] = obj['联系人']
        data_dic['J']['联系人手机'] = obj['联系人手机']
        data_dic['J']['签订单位'] = obj['签订单位']
        data_dic['J']['开始日期'] = obj['开始日期']
        data_dic['J']['终止日期'] = obj['终止日期']
        data_dic['J']['签订日期'] = obj['签订日期']
        data_dic['J']['本单位编号'] = obj['本单位编号']
        data_dic['J']['施工地点'] = obj['施工地点']
        data_dic['J']['合同税率'] = obj['合同税率']
        data_dic['J']['生效日期'] = obj['生效日期']

        xdr_dic['合同相对人名称'] = obj['合同相对人名称']
        xdr_dic['开户城市'] = obj['开户城市']
        xdr_dic['联行名称'] = obj['联行名称']
        xdr_dic['收款开户银行'] = obj['收款开户银行']
        xdr_dic['收款账号'] = obj['收款账号']
        xdr_dic['账户名称'] = obj['账户名称']
        xdr_dic['对方单位税号'] = obj['对方单位税号']
        data_dic['X'].append(xdr_dic)

        
        data = {"contract_id": contract_id, "contract_data": data_dic}
        log.info('return_code is success ' + str(data))
    return {"params":{"code": code, "data": base64.b64encode(json.dumps(data).encode('utf-8')).decode('utf-8') }}


# 发送post请求，获取response
def send_req(url, data, method="POST", headers={'Content-Type': 'application/json'}):
    log.info(u'send_req is start')
    log.info(u'send_req url is ' + str(url))
    try:

        res = requests.request(method, url=url, data=data, headers=headers)
        log.info(u'send_req res is ' + str(res))
        return res
    except Exception as e:
        log.info(u'send_req error is ' + str(e))
        raise Exception('500')


def pdf2txt(pdf_bytes):
    with fitz.Document(stream=pdf_bytes, filetype='pdf') as upload_pdf:
        url = 'http://10.40.39.73:32001/v2/123/ocr/general-text'
        words = ""
        words_fp = ''
        for page_num in range(len(upload_pdf)):
            page = upload_pdf[page_num]
            pix = page.get_pixmap()
            img_data = pix.tobytes()

            base64_data = base64.b64encode(img_data)
            base64_str = str(base64_data, 'utf-8')
            data = json.dumps({'image': base64_str,
                               "detect_direction": False,
                               "quick_mode": False})
            res = send_req(url, data)
            if res == 500:
                raise Exception('500')
            for i in res.json()['result']['words_block_list']:
                words += i['words'] + '\n'
            if page_num == 0:
                words_fp = words

        return words, words_fp


def is_most_in(str1, str2, threshold=0.6):
    # 计算str1中字符在str2中出现的次数
    count = sum(1 for char in str1 if char in str2)
    # 计算str1的长度
    length_str1 = len(str1)
    # 计算比例
    ratio = count / length_str1
    # 判断比例是否达到阈值
    return ratio >= threshold


def write_file(filepath, lines):
    with open(filepath, 'w', encoding='utf-8') as f:
        f.writelines(lines)


def file_read(filepath):
    with open(filepath, 'r', encoding='utf-8') as f:
        read_file = f.read()
    return read_file


def file_readlines(filepath):
    with open(filepath, 'r', encoding='utf-8') as f:
        read_file = f.readlines()
    return read_file


# 合同文本提取字段
def contract_ext(words, arg):
    prompt = prompt_hanlder(words, arg)

    content = {"content": prompt}
    url = 'http://10.40.37.223:8084/v1/chat/completions'

    body = {
        "messages": [content],
        "temperature": 0.1,
        "max_tokens": 700
    }
    res = send_req(url=url, data=json.dumps(body))
    print(res.text)
    if res == 500:
        raise Exception('500')

    message_obj = res.json()["choices"][0]["message"]
    return message_obj


def words_handler(words, fp_words, arg):
    words_list = []
    words_len = len(words)
    pre_w = ''
    for i in range(0, words_len, 7000):
        message_obj = contract_ext(fp_words + pre_w + words[i:i + 7000], arg)
        words_list.append(message_obj)
        pre_w = words[i + 6500:i + 7000]

    return words_list


async def fields_ext(words, first_page, arg='prompt_str'):
    newobj_list = []
    fields_obj = {}

    contact_list = []
    num_list = []
    if arg == 'prompt_contact':
        fields_obj['联系人'] = ''
        fields_obj['联系人手机'] = ''
    if arg == 'prompt_date':
        fields_obj['开始日期'] = ''
        fields_obj['生效日期'] = ''
        fields_obj['终止日期'] = ''
        fields_obj['签订日期'] = ''
    if arg == 'prompt_city':
        fields_obj['开户城市'] = ''
        fields_obj['收款开户银行'] = ''
    if arg == 'prompt_bdwbh':
        words = first_page
    words_len = len(words)

    if words_len > 7000:
        words_list = words_handler(words, first_page, arg)
        for i in words_list:
            new_obj = structured_fields(i, arg)

            newobj_list.append(new_obj)
        if arg == 'prompt_sgdd':
            fields_obj['施工地点'] = ';'.join(list(set([i['施工地点'] for i in newobj_list if i.get('施工地点', '')])))

        if arg == 'prompt_date':
            fields_obj = datefields_handler(newobj_list)
        for i in newobj_list:
            for k, v in i.items():
                if arg == 'prompt_str':
                    if fields_obj.get(k) == None or fields_obj.get(k) == "":
                        fields_obj[k] = v
                elif arg == 'prompt_tax':
                    if '税率' in i['税率条款']:
                        fields_obj = i
                elif arg == 'prompt_city':
                    if '开户城市' in i:
                        if i['开户城市'] != '' and i['开户城市'] != '未提供':
                            if is_most_in(i['开户城市'], i['联行名称']):
                                fields_obj['开户城市'] = i['开户城市']
                    if '收款开户银行' in i:
                        if i['收款开户银行'] != '' and i['收款开户银行'] != '未提供':
                            if '行' in i['收款开户银行']:
                                fields_obj['收款开户银行'] = i['收款开户银行']
                elif arg == 'prompt_contact':
                    contact = '联系人'
                    num = '联系人手机'
                    if contact in i and i['联系人'] != '':
                        contact_list.append(i['联系人'])
                        if len(contact_list) > 1:
                            fields_obj['联系人'] = contact_list[0]
                        else:
                            fields_obj['联系人'] = i['联系人']

                    if num in i and i['联系人手机'] != '':
                        num_list.append(i['联系人手机'])
                        if len(num_list) > 1:
                            fields_obj['联系人手机'] = num_list[0]
                        else:
                            fields_obj['联系人手机'] = i['联系人手机']
    else:
        message_obj = contract_ext(words, arg)
        if message_obj == 500:
            raise Exception('500')
        fields_obj = structured_fields(message_obj, arg)

        if arg == 'prompt_city':
            if fields_obj['开户城市'] != '' and fields_obj['开户城市'] != '未提供':
                if not is_most_in(fields_obj['开户城市'], fields_obj['联行名称']):
                    fields_obj['开户城市'] = ''

            if fields_obj['收款开户银行'] != '' and fields_obj['收款开户银行'] != '未提供':
                if '行' not in fields_obj['收款开户银行']:
                    fields_obj['收款开户银行'] = ''

            if '联行名称' in fields_obj:
                del fields_obj['联行名称']
        if arg == 'prompt_date':
            fields_obj = datefields_handler([fields_obj])

    return fields_obj


def datefields_handler(date_list):
    fields_obj = {
        '开始日期': '',
        '终止日期': '',
        '签订日期': '',
        '生效日期': '',
        '开始日期描述': '',
        '终止日期描述': '',
        '签订日期描述': '',
        '生效日期描述': '',
    }
    if date_list == []:
        return fields_obj
    for date_obj in date_list:

        if date_obj == {}:
            continue

        if date_obj['开始日期'] != '' and date_obj['开始日期描述'] != '':
            fields_obj['开始日期'] = date_obj['开始日期']
            fields_obj['开始日期描述'] = date_obj['开始日期描述']
        if date_obj['终止日期'] != '' and date_obj['终止日期描述'] != '':
            fields_obj['终止日期'] = date_obj['终止日期']
            fields_obj['终止日期描述'] = date_obj['终止日期描述']
        if date_obj['签订日期'] != '' and date_obj['签订日期描述'] != '' and date_obj['签订日期描述'].find('签') > -1:
            fields_obj['签订日期'] = date_obj['签订日期']
            fields_obj['签订日期描述'] = date_obj['签订日期描述']
            if (date_obj['开始日期描述'].find('自签订之日') > -1 or date_obj['开始日期描述'].find('自签订之日')) > -1:
                fields_obj['开始日期'] = date_obj['签订日期']
        if date_obj['生效日期'] != '' and date_obj['生效日期描述'] != '' and date_obj['生效日期描述'].find('生效') > -1:
            fields_obj['生效日期'] = date_obj['生效日期']
            fields_obj['生效日期描述'] = date_obj['生效日期描述']

    return fields_obj


def structured_fields(res, arg='prompt_str'):
    content = res['content']
    ext_str = content[content.find("{"):content.find("}") + 1]
    ext_str = ext_str.replace('\n', '').replace('-"', '"')

    ext_str = content[content.find("{"):content.find("}") + 1]
    ext_str = ext_str.replace('\n', '').replace('-"', '"').replace("'", '"').replace('；', ';')

    ext_obj = {}
    try:
        ext_obj = json.loads(ext_str)
    except json.decoder.JSONDecodeError as e:
        str_list = re.findall('"(.*?)"', ext_str)
        strlist_len = len(str_list)
        for i in range(0, (strlist_len if strlist_len % 2 == 0 else strlist_len - 1), 2):
            ext_obj[str_list[i]] = str_list[i + 1]
    except Exception as e:
        raise Exception('500')

    if arg == 'prompt_bdwbh':
        ext_obj = bdwbh_res_handler(ext_obj)

    new_obj = {}
    for k, v in ext_obj.items():
        k = k.replace('\n', '').replace(' ', '')
        if type(v) == list:
            v = ';'.join(v)
        try:
            v = v.replace('\n', '').replace(' ', '').replace('未提供', '')
            v = v.replace('N/A', '').replace('未提及', '').replace('无', '')
        except Exception as e:
            raise Exception('500')
        new_obj[k] = v

    return new_obj


def bdwbh_res_handler(ext_obj):
    if ext_obj.get('合同编号', '') == '':
        ext_obj['本单位编号'] = ''
        return ext_obj
    ext_list = [i for i in ext_obj.get('合同编号', '').split(';') if i.find('-') > -1]
    ext_obj['本单位编号'] = ';'.join(ext_list)
    del ext_obj['合同编号']
    return ext_obj


def return_data(data):
    data = data.result()
    basedir = os.path.abspath(os.path.dirname(__file__))
    with open(basedir + '/conf.txt', 'r', encoding='utf-8') as f:
        conf_obj = f.read()
    url = json.loads(conf_obj)['dev_url']
    # url = json.loads(conf_obj)['pro_url']
    res = send_req(url, str(data))


async def do_ext(words, first_page):
    task = [
        fields_ext(words, first_page),
        fields_ext(words, first_page, 'prompt_tax'),
        fields_ext(words, first_page, 'prompt_bdwbh'),
        fields_ext(words, first_page, 'prompt_sgdd'),
        fields_ext(words, first_page, 'prompt_city'),
        fields_ext(words, first_page, 'prompt_contact'),
        fields_ext(words, first_page, 'prompt_date'),
    ]
    task_res = await asyncio.gather(*task)
    return task_res
